class_name GravityAttack
extends Node2D

@onready var sprite_2d: Sprite2D = $Parent/Sprite2D
@onready var point_light_2d: PointLight2D = $Parent/PointLight2D

@onready var hit_area: Area2D = $Parent/HitArea
var hit_targets: Array = []

@export var speed: float = 1000
@onready var parent: Node2D = $Parent
var target_pos: Vector2

var hit_ground: bool = false
var is_start_attack: bool = false

@export var shoot_gun_config: ItemGunBaseConfig

var sender: Node2D
var attack: float = 0
var critical_rate: float = 0
var critical_bonus: float = 0
var knockback: float = 0
var affect_vertical_velocity: float = 0
var cam_shake_strength: float = 0
var cam_shake_duration: float = 0

@onready var audio_gravity_hit: AudioStreamPlayer2D = $AudioGravityHit


func start_attack(target_pos: Vector2, hit_ground: bool = false):
	self.target_pos = target_pos
	self.hit_ground = hit_ground
	is_start_attack = true
	fade_show()
	hit_targets = []
	
	var level = get_tree().current_scene as Level
	level.camera.start_shake(cam_shake_strength, cam_shake_duration)
	
	audio_gravity_hit.play()
	

func _physics_process(delta: float) -> void:
	process_hit()
	
	if not is_start_attack:
		return
	
	parent.global_position.y = move_toward(parent.global_position.y, target_pos.y, speed * delta)
	if parent.global_position.y == target_pos.y:
		if hit_ground:
			var level = get_tree().current_scene as Level
			level.emit_particle("particle_hit_ground_burst", target_pos)
			level.camera.start_shake(cam_shake_strength, cam_shake_duration)
			
		is_start_attack = false
		fade_hide()
		

func process_hit():
	var areas = hit_area.get_overlapping_areas()
	if areas.size() <= 0: return
	
	for area in areas:
		var source = area.source as Node2D
		if source.has_method("take_hit") and source not in hit_targets:
			hit_targets.append(source)
			source.take_hit(get_hit_data(), sender)
			
			var level = get_tree().current_scene as Level
			level.camera.start_shake(cam_shake_strength * 2.0, cam_shake_duration * 0.5)
			

func get_hit_data():
	var critical_rate = critical_rate
	var is_critical = (randf() <= critical_rate)
	var critical_attack = attack * (1.0 + critical_bonus)
	
	var hit_data = HitData.new()
	hit_data.is_critical = is_critical
	hit_data.attack = attack if not is_critical else critical_attack
	hit_data.knockback = knockback
	hit_data.affect_vertical_velocity = affect_vertical_velocity
	
	return hit_data


func fade_show():
	var tween_alpha = create_tween()
	tween_alpha.tween_property(sprite_2d.material, "shader_parameter/alpha", 1.0, 0.1) \
	.set_trans(Tween.TRANS_CUBIC) \
	.set_ease(Tween.EASE_OUT).from_current()
	
	tween_alpha = create_tween()
	tween_alpha.tween_property(point_light_2d, "energy", 2.0, 0.1) \
	.set_trans(Tween.TRANS_CUBIC) \
	.set_ease(Tween.EASE_OUT).from_current()
	

func fade_hide():
	var tween_alpha = create_tween()
	tween_alpha.tween_property(sprite_2d.material, "shader_parameter/alpha", 0, 0.5) \
	.set_trans(Tween.TRANS_CUBIC) \
	.set_ease(Tween.EASE_IN).from_current()
	
	tween_alpha = create_tween()
	tween_alpha.tween_property(point_light_2d, "energy", 0.0, 0.5) \
	.set_trans(Tween.TRANS_CUBIC) \
	.set_ease(Tween.EASE_OUT).from_current()
	
	await tween_alpha.finished
	queue_free()
		
	
func set_is_enemy(b: bool):
	if b:
		hit_area.set_collision_mask_value(7, true)
		hit_area.set_collision_mask_value(6, false)
	else:
		hit_area.set_collision_mask_value(7, false)
		hit_area.set_collision_mask_value(6, true)
	
